#include<iostream>
#include<mutex>
using namespace std;
//智能指针：1.RAII特性  2.重载*和->，让类对象像对象一样访问

//auto_ptr:资源所有权转移
template<class T>
class auto_ptr
{
public:
  auto_ptr(T* p = nullptr) :_ptr(p)
  {}
  auto_ptr(const auto_ptr<T>& ap) :_ptr(ap._ptr)
  {
    ap._ptr = nullptr;
  }
  auto_ptr<T>& operator=(const auto_ptr<T>& ap)
  {
    if(this != &ap)
    {
      if(_ptr) delete _ptr; //记得要释放内存！！！
      _ptr = ap._ptr; 
      ap._ptr = nullptr;
    }
    return *this;
  }
  ~auto_ptr()
  {
    if(_ptr)
      delete _ptr;
    _ptr = nullptr;
  }
  T* operator->()
  {
    return _ptr;
  }
  T& operator*()
  {
    return *_ptr;
  }
private:
  T* _ptr;
};


//unique_ptr:通过防拷贝的方式解决智能指针的拷贝问题
template<class T>
class unique_ptr
{
public:
  unique_ptr(const T* p = nullptr) :_ptr(p)
  {}
  ~unique_ptr()
  {
    if(_ptr) delete _ptr;
    _ptr = nullptr;
  }
  T* operator->()
  {
    return _ptr;
  }
  T& operator*()
  {
    return *_ptr;
  }
private:
  unique_ptr(const unique_ptr<T>&) = delete;
  unique_ptr<T>& operator=(const unique_ptr<T>&) = delete;
private:
  T* _ptr;
};

//shared_ptr:通过引用计数的方式,让多个对象可以管理同一个资源
template<class T>
class shared_ptr
{
public:
  shared_ptr(const T* p = nullptr)  :_ptr(p),_pRefCount(new int(1)),_mtx(new mutex)
  {}
  T* operator->()
  {
    return _ptr;
  }
  T& operator*()
  {
    return *_ptr;
  }
  shared_ptr(const shared_ptr<T>& sp) :_ptr(sp._ptr),_pRefCount(sp._pRefCount),_mtx(sp._mtx)
  {
   AddRef(); //记得要增加当前管理资源的引用计数！！！ 
  }
  shared_ptr<T>& operator=(const shared_ptr<T>& sp)
  {
    if(_ptr != sp._ptr)
    {
      ReleaseRef();
      _ptr = sp._ptr;
      _mtx = sp._mtx;
      _pRefCount = sp._pRefCount;
      AddRef();
    }
    return *this;
  }
  void ReleaseRef()
  {
    _mtx->lock(); 
    bool flag = false;
    if(--(*_pRefCount) == 0)
    {
      flag = true;
      delete _ptr;
      delete _pRefCount;
      _ptr = _pRefCount = nullptr;
    }
    _mtx->unlock();
    if(flag)
    {
      delete _mtx;
      _mtx = nullptr;
    }
  }
  void AddRef()
  {
    _mtx->lock();
    (*_pRefCount)++;
    _mtx->unlock();
  }
  ~shared_ptr()
  {
    ReleaseRef();
  }
  T* get() const 
  {
    return _ptr;
  }
  int use_count() const 
  {
    return *_pRefCount;
  }
private:
  T* _ptr;
  int* _pRefCount;
  mutex* _mtx;
};


//weak_ptr并不管理资源,主要是为了解决shared_ptr的循环引用的问题，并不会增加引用计数的数目
template<class T>
class weak_ptr
{
public:
  weak_ptr() :_ptr(nullptr)
  {}
  ~weak_ptr()
  {
    _ptr = nullptr;
  }
  weak_ptr(const shared_ptr<T>& sp)
  {
    _ptr = sp.get();
  }  
private:
  T* _ptr;
};
